package com.dukk.gis.tools.extensions.shadow;


import org.locationtech.jts.geom.Coordinate;
import org.locationtech.jts.geom.CoordinateArrays;
import org.locationtech.jts.geom.GeometryFactory;
import java.util.*;
import java.util.function.Function;

/**
 * 最终合线计算
 *
 */
public class LineLabelPartMerge {

    GeometryFactory geometryFactory = new GeometryFactory();

    Map<Coordinate, CoordinateLabel> coordinateLabelMap;

    public LineLabelPartMerge(Map<Coordinate, CoordinateLabel> coordinateLabelMap){
        this.coordinateLabelMap = coordinateLabelMap;
    }

    public LinkedList<LineLabel> getLineLabelList(Function<Set<Integer>, Integer> partTypeFunction){

        LinkedList<LineLabel> lineLabelList = new LinkedList<>();
        List<Coordinate> tempCoordinateList = new LinkedList<>();
        int i=1;
        Integer tempPartType = PartType.EMPTY;

        for(Coordinate coordinate : this.coordinateLabelMap.keySet()){
            CoordinateLabel coordinateLabel = this.coordinateLabelMap.get(coordinate);
            Integer partType = partTypeFunction.apply(coordinateLabel.getPartTypeSet());
            if(i == 1){
                tempCoordinateList.add(coordinate);
                tempPartType = partType;
            }else {
                if(partType.equals(tempPartType)){
                    tempCoordinateList.add(coordinate);
                    if(i == this.coordinateLabelMap.size()){
                        try {
                            LineLabel lineLabel = createLineLabel(tempCoordinateList, tempPartType);
                            lineLabelList.add(lineLabel);
                        }catch (Exception e){
                            e.printStackTrace();
                        }

                    }
                }else {
                    //判断跳变点给前还是给后(挂接的形状点取谁的问题)
                    Set<Integer> partTypeSet =  coordinateLabel.getPartTypeSet();
                    if(partTypeSet.contains(tempPartType)){ //包含给前
                        //保存上一节
                        tempCoordinateList.add(coordinate);
                        LineLabel lineLabel = createLineLabel(tempCoordinateList, tempPartType);
                        lineLabelList.add(lineLabel);

                        //开启下一节
                        tempCoordinateList = new LinkedList<>();
                        tempCoordinateList.add(coordinate);
                        tempPartType = partType;
                    }else {


                        if(tempCoordinateList.size() <= 1){ //短小节 精度造成的直接归属到下一节
                            Coordinate coordinateBefore = tempCoordinateList.get(0);
                            //开启下一节
                            tempCoordinateList = new LinkedList<>();
                            tempCoordinateList.add(coordinateBefore);
                            tempPartType = partType;
                        }else {
                            //保存上一节
                            LineLabel lineLabel = createLineLabel(tempCoordinateList, tempPartType);
                            lineLabelList.add(lineLabel);

                            //开启下一节
                            tempCoordinateList = new LinkedList<>();
                            tempCoordinateList.add(lineLabel.getLastCoordinate());
                            tempCoordinateList.add(coordinate);
                            tempPartType = partType;

                            if(i == this.coordinateLabelMap.size()){ //最后一节
                                LineLabel lineLabelLast = createLineLabel(tempCoordinateList, tempPartType);
                                lineLabelList.add(lineLabelLast);
                            }
                        }
                    }
                }
            }

            i++;
        }

        return lineLabelList;
    }

    private LineLabel createLineLabel(List<Coordinate> coordinateList, Integer partType){
        Coordinate[] coordinates = CoordinateArrays.toCoordinateArray(coordinateList);

        Coordinate[] coordinatesNoRepeated = CoordinateArrays.removeRepeatedPoints(coordinates);

        LineLabel lineLabel = new LineLabel();

        lineLabel.setLineString(geometryFactory.createLineString(coordinatesNoRepeated));
        lineLabel.setPartType(partType);

        return lineLabel;
    }


}
